"""
author：fc
date：  2021/10/5
"""
# knn算法的实现
#
import os
import numpy as np
import operator  # 用于排序
from PIL import Image

'''
补充使用：
扩展函数np.tile(array,(扩展次数,扩展方向【1为列，0为行】))
'''


def knn(k, testdata, train_data, train_lables):
    train_data_size = train_data.shape[0]
    diff =np.tile(testdata, (train_data_size, 1)) - train_data  # 将一维数组转换为二维数组（向行扩充），每一行都一样，再和训练集做差
    sq_diff = diff ** 2
    sum_sq_diff = sq_diff.sum(axis=1)
    distance = sum_sq_diff ** 0.5
    sort_distance = distance.argsort()  # 返回排序后的索引列表list ,list[0]=原数组索引，代表数组中最小值所在的索引
    count = {}
    for i in range(0, k):
        vote = train_lables[sort_distance[i]]
        count[vote] = count.get(vote, 0) + 1
    sort_count = sorted(count.items(), key=operator.itemgetter(1), reverse=True)  # 降序排序
    return sort_count[0][0]


def img_convert_txt():
    """
    图片转文本
    :return:
    """
    im = Image.open("G:/Installation_Directories/微信/WeChat Files/All Users/bb61858736b236369d8046c45758e688.jpg")
    print(str(im.size[0]) + '   ' + str(im.size[1]))  # 长宽
    # im.getpixel((1,9)) #像素点颜色，三元一维数组
    fh = open("../files/数据建模/写入mnist.txt", "a")
    for i in range(0, im.size[0]):
        for j in range(0, im.size[1]):
            color = im.getpixel((i, j))
            color_all = color[0] + color[1] + color[2]
            if color_all == 255:  # 黑色
                fh.write("1")
            else:
                fh.write("0")
        fh.write("\n")
    fh.close()


def data_to_array(filename):
    arr = []
    fh = open(filename, 'r')
    for i in range(0, 32):
        thisline = fh.readline()
        for j in range(0, 32):
            arr.append(int(thisline[j]))

    return arr


def slipt_str(str_filename):
    file_str = str_filename.split(".")[0]
    return int(file_str.split("_")[0])


def get_data(dir):
    labels = []
    file_txts = os.listdir(dir)
    count = len(file_txts)
    data = np.zeros((count, 1024),int)  # 所有训练数据
    for i in range(len(file_txts)):
        this_label = slipt_str(file_txts[i])
        labels.append(this_label)
        data[i, :] = data_to_array(dir + file_txts[i])
    return data, labels


def data_test():
    train_data, train_labels = get_data("../files/digits/trainingDigits/")
    test_data, test_labels = get_data("../files/digits/testDigits/")
    corr_count=0
    for j in range(len(test_data)):
        pre_val=knn(3,test_data[j],train_data,train_labels)
        print(f"预测值：{pre_val}  真实值：{test_labels[j]}")
        if pre_val==test_labels[j]:
            corr_count += 1
    corr_rate=corr_count/len(test_data)
    print(f"准确率：{corr_rate}")

if __name__ == '__main__':
    data_test()
